<?php
declare (strict_types=1);

namespace app\common\queue\learn;

use app\common\exception\LogicException;
use app\course\logic\base\CourseSection;
use app\course\logic\base\CourseStudent;
use app\course\logic\classes\ClassesLink;
use app\course\model\record\LearnCourseFinished as Finished;
use app\course\model\record\LearnCourseRate as RateMod;
use app\course\model\record\LearnCourseRecord as Record;
use think\annotation\Inject;
use think\facade\Request;

/**
 * 用户学习进度计算类
 */
class Rate
{
    /**
     * @Inject()
     * @var Record
     */
    protected $recordMod;

    protected $mid;

    protected $courseId;

    public function __construct()
    {
        $data           = Request::post();
        $this->mid      = $data['mid'] ?? 0;
        $this->courseId = $data['course_id'] ?? 0;
    }

    public function run()
    {
        // 参数
        $time      = time();
        $mid       = $this->mid;
        $course_id = $this->courseId;

        $update_time = $this->recordMod->mid($mid)->course($course_id)->order('update_time', 'DESC')->value('update_time');
        $course_type = $this->recordMod->mid($mid)->course($course_id)->value('course_type');
        // 去重
        $cache = 'time_' . $mid . '_' . $course_id;
        $ctime = cache($cache);
        if ($ctime == $time) return;
        cache($cache, $time, 1);

        if (($time - $update_time) > 10) {
            // 距上次更新记录超过10秒，表示用户已结束学习
            // 计算进度并添加进度
            $this->calculateRate($course_id, $course_type);
        }
    }

    /**
     * 计算完成率
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-15
     */
    protected function calculateRate($course_id, $course_type)
    {
        $mid = $this->mid;
        // 当前用户此课程学习进度总时间
        $total_time = $this->recordMod->unfinished($course_id, $mid)->sum('total_time');
        // 当前用户此课程课时总时间
        $total_duration = $this->recordMod->unfinished($course_id, $mid)->sum('section_duration');
        // 当前用户此课程已完成的课时
        $finished = $this->recordMod->finished($course_id, $mid)->count();
        // 未完成课时进度
        $unfinished_rate = $total_duration ? round($total_time / $total_duration, 2) : 0;
        // 总课时
        $section_count = app(CourseSection::class)->getCourseSectionCount($course_id);
        // 课程进度
        $finished_rate = $section_count ? ($finished * 100 + $unfinished_rate * 100) / $section_count : 0;
        // 已完成的课程
        if ($finished_rate === 100) {
            $exist = app(Finished::class)->where('user_id', $mid)->where('course_id', $course_id)->lock(true)->findOrEmpty();
            if ($exist->isEmpty()) {
                Finished::create([
                    'user_id'   => $mid,
                    'course_id' => $course_id,
                ]);
            }
            $rate = 100;
        } else {
            $rate = ceil($finished_rate);
            $rate = $rate == 100 ? 99 : $rate;
        }
        // 写入进度
        $exist = app(RateMod::class)->where('user_id', $mid)->where('course_id', $course_id)->lock(true)->findOrEmpty();

        if ($exist->isEmpty()) {
            $add    = RateMod::create([
                'user_id'     => $mid,
                'course_id'   => $course_id,
                'course_type' => $course_type,
                'rate'        => $rate,
            ]);
            $result = !$add->isEmpty();
        } else {
            $exist->rate = $rate;
            $result      = $exist->save();
        }

        // 处理失败，抛出异常即可
        if (!$result) throw new LogicException('learn rate error');
        // 班级课进度
        $classes_id = app(CourseStudent::class)->courseBelongsUserClasses($course_id, $mid);
        if ($classes_id) $this->handleClassesRate($classes_id);
    }

    public function handleClassesRate($classes_id)
    {
        $mid        = $this->mid;
        $course_ids = app(ClassesLink::class)->getCourseIds($classes_id);
        $count      = count($course_ids);

        $rate_sum     = app(RateMod::class)->where('course_id', 'IN', $course_ids)->where('user_id', $mid)->sum('rate');
        $classes_rate = $rate_sum / $count;
        $classes_rate = $classes_rate == 100 ? 100 : (ceil($classes_rate) == 100 ? 99 : ceil($classes_rate));

        $classes_finished = app(Finished::class)->where('user_id', $mid)->where('course_id', $classes_id)->lock(true)->findOrEmpty();
        if ($classes_finished->isEmpty() && $classes_rate == 100) {
            Finished::create([
                'user_id'   => $mid,
                'course_id' => $classes_id,
            ]);
        }

        $exist_classes = app(RateMod::class)->where('course_id', $classes_id)->where('user_id', $mid)->lock(true)->findOrEmpty();
        if ($exist_classes->isEmpty()) {
            RateMod::create([
                'user_id'     => $mid,
                'course_id'   => $classes_id,
                'rate'        => $classes_rate,
                'course_type' => 4
            ]);
        } else {
            $exist_classes->rate = $classes_rate;
            $exist_classes->save();
        }
    }
}
